/* Copyright 2001,2002,2003 NAH6
 * All Rights Reserved
 *
 * Parts Copyright DoD, Parts Copyright Starium
 *
 */
#include "auto_cor.h"

/**************************************************************************
*                                                                         *
* ROUTINE
*               AutoCor
*
* FUNCTION
*               Calculate the autocorrelations for a frame of speech
* SYNOPSIS
*               AutoCor(speech_in, ac)
*
*   formal
*
*                       data    I/O
*       name            type    type    function
*       -------------------------------------------------------------------
*       speech_in       fxpt_16   i     Frame of input speech
*       ac              fxpt_32   o     Autocorrelations
*
**************************************************************************/

/*
 *  I tried hard to find a way to organize the code so it could take
 *  advantage of the 64 bit mips accumulator, but to no avail w/o
 *  causing probs in the output speech.  The following versions are
 *  binary backwards compatible with the version in lp_anal.c.  (The
 *  second implementation is more cryptic, but gcc optimizes it much
 *  better on the mips).
 *
 *  - DH  (9/11/00)
 */


#if 0
void AutoCor(
  fxpt_16       speech_in[F_LEN],               /* 15.0 format */
  fxpt_32       ac[ORDER+1])                    /* 30.1 format */
{
  int i, j;
  fxpt_32 acc;
  fxpt_32 temp;

  for (i = 0; i < ORDER + 1; i++) {
    acc = 0;
    for (j = i; j < F_LEN; j++) {
      temp = speech_in[j] * speech_in[j-i];
      temp >>= 5;
      acc += temp;
    }
    ac[i] = acc;
  }
}
#endif



void AutoCor(
  fxpt_16       speech_in[F_LEN],               /* 15.0 format */
  fxpt_32       ac[ORDER+1])                    /* 30.1 format */
{
  fxpt_64 acc;
#if 0
  fxpt_32 temp;
#endif
  fxpt_16 *spi1, *spi2;
  fxpt_16 *spi1_start;

  spi1_start     = &speech_in[0];

  do {
    acc = 0;

    spi1 = spi1_start++;
    spi2 = &speech_in[0];

    do {
#if 1
      acc += *spi1++ * *spi2++;
#else
      temp = *spi1 * *spi2;
      temp >>= 5;
      acc += temp;
      spi1++;
      spi2++;
#endif
    } while (spi1 != &speech_in[F_LEN]);

    *ac = fxpt_saturate32_round( acc, 6 );
    ac++;

  } while (spi1_start != &speech_in[ORDER+1]);
}
